package cn.foolishbird.basic.util;

import cn.foolishbird.basic.cache.Cache;
import cn.foolishbird.basic.cache.CacheException;
import cn.foolishbird.basic.cache.MemoryConstrainedCacheManager;
import cn.foolishbird.basic.cache.MemoryWeakCacheManager;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 反射 缓存
 *
 * @author Eric
 * @version 1.0
 * @date 2019-12-13
 */
public class ReflectCache {

    private static final String CONSTRUCTOR = "constructor";

    private static final String METHOD = "method";

    private static final String FIELD = "field";

    private static final MemoryWeakCacheManager caches = new MemoryWeakCacheManager();


    public static Method getMthod(Class<?> cls, String name, Class<?>... parameterTypes) throws CacheException, NoSuchMethodException {
        // 先查询缓存
        String key = key(cls.getName(), name, parameterTypes);
        Cache<String, Method> methodCache = caches.getCache(METHOD);
        Method method = methodCache.get(key);
        if (method == null) {
            method = cls.getMethod(name, parameterTypes);
            methodCache.put(key, method);
        }
        return method;
    }

    public static Constructor getConstructor(Class<?> cls, Class<?>... parameterTypes) throws CacheException, NoSuchMethodException {
        String key = key(cls.getName(), null, parameterTypes);
        Cache<String, Constructor> constructorCache = caches.getCache(CONSTRUCTOR);
        Constructor constructor = constructorCache.get(key);
        if (constructor == null) {
            constructor = cls.getConstructor(parameterTypes);
            constructorCache.put(key, constructor);
        }
        return constructor;
    }


    /**
     * 拼接缓存key
     *
     * @param className      class权限定名
     * @param name           可能是方法名，也可能是属性名
     * @param parameterTypes 参数类型
     * @return java.lang.String
     * @throws
     * @author Eric
     * @date 2019/12/16
     **/
    private static String key(String className, String name, Class<?>... parameterTypes) {
        if (StrUtil.isBlank(className)) {
            return null;
        }
        StringBuilder key = new StringBuilder(className);
        if (StrUtil.isNotBlank(name)) {
            key.append("#").append(name);
        }
        for (Class<?> c : parameterTypes) {
            key.append("#");
            key.append(c.getTypeName());
        }
        return key.toString();
    }

    private void initClass(Class<?> cls) throws CacheException {
        Cache<String, Constructor> cache = caches.getCache(CONSTRUCTOR);
        Constructor[] constructors = cls.getConstructors();
        Arrays.stream(constructors).forEach(con -> {
//            cache.get()
        });
    }

}
